Skip to content

Reporting table filters#4

Draft
pelted wants to merge 13 commits into
mainfrom
chris/reporting-table-filters
Draft

Reporting table filters#4
pelted wants to merge 13 commits into
mainfrom
chris/reporting-table-filters

Conversation

@pelted
Copy link
Copy Markdown
Contributor

@pelted pelted commented Apr 6, 2026

Draft PR for reporting table filtering

pelted added 13 commits March 23, 2026 11:22
Adds config.py with a ServerConfig dataclass that reads all server
settings from environment variables in one place. Updates server.py to
use ServerConfig for host, port, and debug mode, removing scattered
os.getenv calls.

Defaults MCP_HOST to 127.0.0.1 (was 0.0.0.0), limiting the server to
loopback-only by default. MCP_DEBUG defaults to false; the env var is
retained for local development use only.

Addresses findings 2 (0.0.0.0 binding) and 8 (debug mode exposure).
Replaces the wildcard Access-Control-Allow-Origin: * header with
Starlette's CORSMiddleware, gated by MCP_CORS_ALLOWED_ORIGINS
(defaults to http://localhost,http://127.0.0.1).

Removes the manual OPTIONS handler from the MCP ASGI app; CORSMiddleware
handles preflight responses automatically for all routes.

Addresses finding 1 (wildcard CORS).
Adds BearerAuthMiddleware that validates Authorization: Bearer <token>
on all requests to the MCP endpoints. The /health endpoint is exempt
so monitoring can run without credentials.

The server refuses to start with a descriptive error if MCP_AUTH_TOKEN
is not set, directing the operator to generate a token.

Addresses finding 3 (no server-side authentication on MCP endpoint).
Parses the upstream error response body and extracts only the
message or error field. Falls back to a generic HTTP status string
if parsing fails or neither field is present. This prevents raw
internal error bodies (request IDs, field validation details, etc.)
from reaching MCP callers.

Addresses finding 6 (raw API error bodies surfaced to callers).
Without a cap, combining fetch_all=true with enrich_device_owner=true
could trigger up to 20,000 upstream API calls per tool invocation
(2 calls per record × 10,000 max records), exhausting rate limits.

Enrichment is now limited to MCP_MAX_ENRICH_RECORDS records per call
(default 500). When the cap is reached, enrichment_truncated: true and
enrichment_limit are included in the response so callers can detect
partial enrichment.

Addresses finding 5 (API call amplification).
Removes uv.lock from .gitignore and commits the lockfile so that
uv sync --frozen on any machine or CI environment resolves the exact
same dependency versions that were tested, preventing unexpected
package upgrades (including potentially malicious PyPI publishes).

Addresses finding 7 (unpinned dependency versions).
Adds KNOWN_REPORTING_TABLES, a versioned frozenset of valid reporting
table names (Kolide API version 2023-05-26). handle_count_table_records_by_field
rejects any table_name not in the set, returning the list of valid tables.

This prevents user-controlled input from being interpolated into URL paths
without validation. A comment in the code documents the regex alternative
for operators who need maintenance-free name validation.

Addresses finding 9 (table_name interpolated directly into URL path).
Adds logging_config.py with a StructuredFormatter that emits one JSON
object per log line. Logs are written to stdout by default; setting
MCP_LOG_FILE also writes to a file.

Each tool call is logged with timestamp, tool name, argument keys (not
values, to avoid logging sensitive data), and the source IP captured via
a ContextVar set by a new RequestContextMiddleware.

Addresses finding 11 (no audit logging).
Introduces a new ReportingTableRegistry class to manage valid reporting table names dynamically fetched from the Kolide API. This includes methods for loading, refreshing, and validating table names, enhancing the previous static validation approach. A new tool, 'kolide_refresh_reporting_tables', is added to allow on-demand refresh of the table list. Updates to the server initialization ensure the registry is loaded at startup, improving the handling of table name validation in API calls.

Addresses findings related to outdated table name handling and improves overall API robustness.
Enhances the .env.example file by adding required and optional environment variables for MCP, including MCP_AUTH_TOKEN, MCP_CORS_ALLOWED_ORIGINS, MCP_MAX_ENRICH_RECORDS, MCP_LOG_FILE, and MCP_DEBUG. Updates README.md to reflect these changes, providing clear instructions on setting up the environment variables and highlighting new features such as bearer token authentication and structured JSON audit logging. This improves user guidance for configuring the MCP server.
… URL

Enhances the .env.example file by adding a comment for the optional KOLIDE_API_URL variable, allowing users to override the default API base URL for local development. Updates the KolideClient class to use this environment variable, improving flexibility in API endpoint configuration. This change facilitates easier local testing and development without modifying the source code.
Enhances the EndpointSpec class by introducing a new 'supports_filters' attribute, allowing endpoints to specify if they support filtering. Updates the 'get_table_records' endpoint to enable filtering capabilities, providing detailed descriptions for filter usage. Modifies the dispatch function to handle filter parameters, ensuring that users can filter results based on column values. This improves the API's flexibility and usability for querying reporting data.
… API

Updates the build_tool function to clarify the expected format for filter values in the API documentation, specifying that values should be single IDs or comma-separated lists of IDs. Enhances the _dispatch function to construct query clauses based on filter values, improving the handling of filter parameters and ensuring proper formatting for both single and multiple values. This change enhances the usability and clarity of the API for users filtering reporting data.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant